/**
 * 设备数据同步管理模块
 * 用于处理不同类型健康设备的数据读取、转换和保存
 */

const api = require('./api');
const request = require('./request');

// 设备同步管理器
const DeviceSyncManager = {
  // 当前连接的设备
  currentDevice: null,
  
  // 当前设备特征值
  characteristics: [],
  
  // 设备连接状态
  isConnected: false,
  
  // 数据缓冲区
  dataBuffer: [],
  
  /**
   * 连接并同步设备数据
   * @param {Object} device 设备信息对象
   * @returns {Promise}
   */
  async connectAndSync(device) {
    try {
      console.log('开始连接设备:', device);
      
      // 重置状态
      this.reset();
      
      // 保存当前设备信息
      this.currentDevice = device;
      
      // 连接到BLE设备
      await this.connectToDevice(device.deviceId);
      
      // 根据设备类型执行不同的同步逻辑
      if (device.type === 'glucose') {
        await this.syncGlucoseData();
      } else if (device.type === 'bloodPressure') {
        await this.syncBloodPressureData();
      } else if (device.type === 'weight') {
        await this.syncWeightData();
      } else {
        throw new Error('不支持的设备类型');
      }
      
      // 更新设备同步时间
      await this.updateDeviceSyncTime(device._id);
      
      return {
        success: true,
        message: '数据同步成功'
      };
    } catch (error) {
      console.error('设备同步失败:', error);
      
      // 确保断开连接
      if (this.isConnected) {
        this.disconnectDevice();
      }
      
      return {
        success: false,
        message: error.message || '设备同步失败'
      };
    }
  },
  
  /**
   * 连接到蓝牙设备
   * @param {string} deviceId 设备ID
   * @returns {Promise}
   */
  connectToDevice(deviceId) {
    return new Promise((resolve, reject) => {
      wx.createBLEConnection({
        deviceId: deviceId,
        success: async (res) => {
          console.log('设备连接成功:', res);
          this.isConnected = true;
          
          try {
            // 获取设备的服务
            const services = await this.getDeviceServices(deviceId);
            
            // 获取特征值
            await this.getDeviceCharacteristics(deviceId, services);
            
            resolve();
          } catch (error) {
            this.disconnectDevice();
            reject(error);
          }
        },
        fail: (err) => {
          console.error('设备连接失败:', err);
          reject(new Error('设备连接失败'));
        }
      });
    });
  },
  
  /**
   * 获取设备服务
   * @param {string} deviceId 设备ID
   * @returns {Promise<Array>} 服务ID列表
   */
  getDeviceServices(deviceId) {
    return new Promise((resolve, reject) => {
      wx.getBLEDeviceServices({
        deviceId: deviceId,
        success: (res) => {
          console.log('获取设备服务成功:', res.services);
          
          // 筛选所需的服务UUID
          const serviceIds = res.services.map(service => service.uuid);
          resolve(serviceIds);
        },
        fail: (err) => {
          console.error('获取设备服务失败:', err);
          reject(new Error('获取设备服务失败'));
        }
      });
    });
  },
  
  /**
   * 获取设备特征值
   * @param {string} deviceId 设备ID
   * @param {Array} services 服务ID列表
   * @returns {Promise}
   */
  async getDeviceCharacteristics(deviceId, services) {
    // 清空特征值列表
    this.characteristics = [];
    
    // 遍历服务列表，获取特征值
    for (const serviceId of services) {
      await new Promise((resolve, reject) => {
        wx.getBLEDeviceCharacteristics({
          deviceId: deviceId,
          serviceId: serviceId,
          success: (res) => {
            console.log(`服务 ${serviceId} 的特征值:`, res.characteristics);
            
            // 保存特征值信息
            res.characteristics.forEach(item => {
              this.characteristics.push({
                serviceId: serviceId,
                characteristicId: item.uuid,
                properties: item.properties
              });
            });
            
            resolve();
          },
          fail: (err) => {
            console.warn(`获取服务 ${serviceId} 特征值失败:`, err);
            // 继续处理其他服务，不中断
            resolve();
          }
        });
      });
    }
    
    if (this.characteristics.length === 0) {
      throw new Error('未找到可用的特征值');
    }
    
    return this.characteristics;
  },
  
  /**
   * 断开设备连接
   */
  disconnectDevice() {
    if (this.currentDevice && this.isConnected) {
      wx.closeBLEConnection({
        deviceId: this.currentDevice.deviceId,
        success: () => {
          console.log('设备连接已断开');
          this.isConnected = false;
        },
        fail: (err) => {
          console.error('断开设备连接失败:', err);
        }
      });
    }
  },
  
  /**
   * 重置状态
   */
  reset() {
    // 断开之前的连接
    if (this.isConnected && this.currentDevice) {
      this.disconnectDevice();
    }
    
    this.currentDevice = null;
    this.characteristics = [];
    this.isConnected = false;
    this.dataBuffer = [];
  },
  
  /**
   * 更新设备同步时间
   * @param {string} deviceId 设备ID
   * @returns {Promise}
   */
  async updateDeviceSyncTime(deviceId) {
    try {
      const response = await api.device.updateDeviceSync(deviceId);
      console.log('更新设备同步时间结果:', response);
      return response;
    } catch (error) {
      console.error('更新设备同步时间失败:', error);
      throw error;
    }
  },
  
  /**
   * 同步血糖仪数据
   * @returns {Promise}
   */
  async syncGlucoseData() {
    return new Promise(async (resolve, reject) => {
      try {
        // 查找血糖数据特征值
        const dataCharacteristic = this.findDataCharacteristic('glucose');
        if (!dataCharacteristic) {
          reject(new Error('未找到血糖数据特征值'));
          return;
        }
        
        // 设置数据通知
        await this.enableNotification(dataCharacteristic);
        
        // 监听数据接收
        wx.onBLECharacteristicValueChange((res) => {
          const buffer = new Uint8Array(res.value);
          console.log('接收到血糖数据:', buffer);
          
          // 解析血糖数据
          const glucoseData = this.parseGlucoseData(buffer);
          if (glucoseData) {
            this.dataBuffer.push(glucoseData);
          }
        });
        
        // 发送读取历史数据命令
        await this.sendCommand(dataCharacteristic, this.getGlucoseReadCommand());
        
        // 等待一段时间接收数据 (实际应根据设备协议调整)
        setTimeout(async () => {
          // 移除监听
          wx.offBLECharacteristicValueChange();
          
          if (this.dataBuffer.length === 0) {
            resolve({
              success: true,
              message: '没有新的血糖数据',
              recordCount: 0
            });
            return;
          }
          
          // 保存收集到的血糖数据
          const saveResults = await this.saveGlucoseRecords(this.dataBuffer);
          
          resolve({
            success: true,
            message: `同步了 ${saveResults.length} 条血糖记录`,
            recordCount: saveResults.length
          });
        }, 5000); // 等待5秒
        
      } catch (error) {
        reject(error);
      }
    });
  },
  
  /**
   * 同步血压计数据
   * @returns {Promise}
   */
  async syncBloodPressureData() {
    return new Promise(async (resolve, reject) => {
      try {
        // 查找血压数据特征值
        const dataCharacteristic = this.findDataCharacteristic('bloodPressure');
        if (!dataCharacteristic) {
          reject(new Error('未找到血压数据特征值'));
          return;
        }
        
        // 设置数据通知
        await this.enableNotification(dataCharacteristic);
        
        // 监听数据接收
        wx.onBLECharacteristicValueChange((res) => {
          const buffer = new Uint8Array(res.value);
          console.log('接收到血压数据:', buffer);
          
          // 解析血压数据
          const bpData = this.parseBloodPressureData(buffer);
          if (bpData) {
            this.dataBuffer.push(bpData);
          }
        });
        
        // 发送读取历史数据命令
        await this.sendCommand(dataCharacteristic, this.getBloodPressureReadCommand());
        
        // 等待一段时间接收数据 (实际应根据设备协议调整)
        setTimeout(async () => {
          // 移除监听
          wx.offBLECharacteristicValueChange();
          
          if (this.dataBuffer.length === 0) {
            resolve({
              success: true,
              message: '没有新的血压数据',
              recordCount: 0
            });
            return;
          }
          
          // 保存收集到的血压数据
          const saveResults = await this.saveBloodPressureRecords(this.dataBuffer);
          
          resolve({
            success: true,
            message: `同步了 ${saveResults.length} 条血压记录`,
            recordCount: saveResults.length
          });
        }, 5000); // 等待5秒
        
      } catch (error) {
        reject(error);
      }
    });
  },
  
  /**
   * 同步体重秤数据
   * @returns {Promise}
   */
  async syncWeightData() {
    return new Promise(async (resolve, reject) => {
      try {
        // 查找体重数据特征值
        const dataCharacteristic = this.findDataCharacteristic('weight');
        if (!dataCharacteristic) {
          reject(new Error('未找到体重数据特征值'));
          return;
        }
        
        // 设置数据通知
        await this.enableNotification(dataCharacteristic);
        
        // 监听数据接收
        wx.onBLECharacteristicValueChange((res) => {
          const buffer = new Uint8Array(res.value);
          console.log('接收到体重数据:', buffer);
          
          // 解析体重数据
          const weightData = this.parseWeightData(buffer);
          if (weightData) {
            this.dataBuffer.push(weightData);
          }
        });
        
        // 发送读取历史数据命令
        await this.sendCommand(dataCharacteristic, this.getWeightReadCommand());
        
        // 等待一段时间接收数据 (实际应根据设备协议调整)
        setTimeout(async () => {
          // 移除监听
          wx.offBLECharacteristicValueChange();
          
          if (this.dataBuffer.length === 0) {
            resolve({
              success: true,
              message: '没有新的体重数据',
              recordCount: 0
            });
            return;
          }
          
          // 保存收集到的体重数据
          const saveResults = await this.saveWeightRecords(this.dataBuffer);
          
          resolve({
            success: true,
            message: `同步了 ${saveResults.length} 条体重记录`,
            recordCount: saveResults.length
          });
        }, 5000); // 等待5秒
        
      } catch (error) {
        reject(error);
      }
    });
  },
  
  /**
   * 启用特征值通知
   * @param {Object} characteristic 特征值对象
   * @returns {Promise}
   */
  enableNotification(characteristic) {
    return new Promise((resolve, reject) => {
      wx.notifyBLECharacteristicValueChange({
        deviceId: this.currentDevice.deviceId,
        serviceId: characteristic.serviceId,
        characteristicId: characteristic.characteristicId,
        state: true,
        success: () => {
          console.log('启用通知成功');
          resolve();
        },
        fail: (err) => {
          console.error('启用通知失败:', err);
          reject(new Error('启用通知失败'));
        }
      });
    });
  },
  
  /**
   * 发送命令到设备
   * @param {Object} characteristic 特征值对象
   * @param {ArrayBuffer} command 命令数据
   * @returns {Promise}
   */
  sendCommand(characteristic, command) {
    return new Promise((resolve, reject) => {
      wx.writeBLECharacteristicValue({
        deviceId: this.currentDevice.deviceId,
        serviceId: characteristic.serviceId,
        characteristicId: characteristic.characteristicId,
        value: command,
        success: () => {
          console.log('写入命令成功');
          resolve();
        },
        fail: (err) => {
          console.error('写入命令失败:', err);
          reject(new Error('写入命令失败'));
        }
      });
    });
  },
  
  /**
   * 查找指定类型设备的数据特征值
   * @param {string} deviceType 设备类型
   * @returns {Object|null} 特征值对象
   */
  findDataCharacteristic(deviceType) {
    // 根据设备类型查找对应的特征值
    // 实际应用中需要根据具体设备的UUID来匹配
    
    // 这里仅作示例，实际使用时需替换为真实的UUID
    const uuidMap = {
      glucose: '1808', // 血糖服务UUID (部分)
      bloodPressure: '1810', // 血压服务UUID (部分)
      weight: '181D'  // 体重服务UUID (部分)
    };
    
    const targetUUIDPart = uuidMap[deviceType];
    
    // 查找包含目标UUID的特征值
    for (const char of this.characteristics) {
      if (char.serviceId.includes(targetUUIDPart) && char.properties.read) {
        return char;
      }
    }
    
    // 如果找不到匹配的，返回第一个可读的特征值
    const readableChar = this.characteristics.find(char => char.properties.read);
    return readableChar || null;
  },
  
  /**
   * 解析血糖数据
   * @param {Uint8Array} buffer 数据缓冲区
   * @returns {Object|null} 解析后的血糖数据
   */
  parseGlucoseData(buffer) {
    try {
      // 这里是血糖仪数据解析逻辑
      // 注意：每个品牌/型号的设备数据格式都不同，这只是一个示例
      
      // 示例：假设前两个字节是血糖值(mg/dL)，接下来4个字节是时间戳
      if (buffer.length < 6) return null;
      
      // 解析血糖值 (假设是小端格式，单位mg/dL)
      const glucoseValue = buffer[0] + (buffer[1] << 8);
      
      // 解析时间戳 (假设是小端格式，32位Unix时间戳)
      const timestamp = buffer[2] + (buffer[3] << 8) + (buffer[4] << 16) + (buffer[5] << 24);
      const measuredAt = new Date(timestamp * 1000).toISOString();
      
      // 单位转换 (mg/dL到mmol/L)
      const valueInMmolL = (glucoseValue / 18).toFixed(1);
      
      // 构建血糖数据对象
      return {
        value: valueInMmolL,
        valueInMgDl: glucoseValue,
        measuredAt,
        deviceId: this.currentDevice.deviceId,
        deviceName: this.currentDevice.name,
        mealTime: 'unknown' // 默认未知餐时
      };
    } catch (error) {
      console.error('解析血糖数据失败:', error);
      return null;
    }
  },
  
  /**
   * 解析血压数据
   * @param {Uint8Array} buffer 数据缓冲区
   * @returns {Object|null} 解析后的血压数据
   */
  parseBloodPressureData(buffer) {
    try {
      // 这里是血压计数据解析逻辑
      // 注意：每个品牌/型号的设备数据格式都不同，这只是一个示例
      
      // 示例：假设前两个字节是舒张压，接下来两个字节是收缩压，再接下来4个字节是时间戳
      if (buffer.length < 8) return null;
      
      // 解析舒张压
      const diastolic = buffer[0] + (buffer[1] << 8);
      
      // 解析收缩压
      const systolic = buffer[2] + (buffer[3] << 8);
      
      // 解析时间戳 (假设是小端格式，32位Unix时间戳)
      const timestamp = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24);
      const measuredAt = new Date(timestamp * 1000).toISOString();
      
      // 构建血压数据对象
      return {
        systolic,
        diastolic,
        pulse: 0, // 脉搏默认值，如果设备提供可以解析
        measuredAt,
        deviceId: this.currentDevice.deviceId,
        deviceName: this.currentDevice.name
      };
    } catch (error) {
      console.error('解析血压数据失败:', error);
      return null;
    }
  },
  
  /**
   * 解析体重数据
   * @param {Uint8Array} buffer 数据缓冲区
   * @returns {Object|null} 解析后的体重数据
   */
  parseWeightData(buffer) {
    try {
      // 这里是体重秤数据解析逻辑
      // 注意：每个品牌/型号的设备数据格式都不同，这只是一个示例
      
      // 示例：假设前四个字节是体重值(浮点数)，接下来4个字节是时间戳
      if (buffer.length < 8) return null;
      
      // 解析体重值 (假设是IEEE-754浮点数表示，单位kg)
      const weightDataView = new DataView(buffer.buffer);
      const weightValue = weightDataView.getFloat32(0, true); // 小端格式
      
      // 解析时间戳 (假设是小端格式，32位Unix时间戳)
      const timestamp = buffer[4] + (buffer[5] << 8) + (buffer[6] << 16) + (buffer[7] << 24);
      const measuredAt = new Date(timestamp * 1000).toISOString();
      
      // 构建体重数据对象
      return {
        value: weightValue.toFixed(1),
        measuredAt,
        deviceId: this.currentDevice.deviceId,
        deviceName: this.currentDevice.name
      };
    } catch (error) {
      console.error('解析体重数据失败:', error);
      return null;
    }
  },
  
  /**
   * 获取血糖读取命令
   * @returns {ArrayBuffer} 命令数据
   */
  getGlucoseReadCommand() {
    // 示例命令，根据实际设备协议替换
    const cmd = new Uint8Array([0x01, 0x02, 0x03]);
    return cmd.buffer;
  },
  
  /**
   * 获取血压读取命令
   * @returns {ArrayBuffer} 命令数据
   */
  getBloodPressureReadCommand() {
    // 示例命令，根据实际设备协议替换
    const cmd = new Uint8Array([0x04, 0x05, 0x06]);
    return cmd.buffer;
  },
  
  /**
   * 获取体重读取命令
   * @returns {ArrayBuffer} 命令数据
   */
  getWeightReadCommand() {
    // 示例命令，根据实际设备协议替换
    const cmd = new Uint8Array([0x07, 0x08, 0x09]);
    return cmd.buffer;
  },
  
  /**
   * 保存血糖记录
   * @param {Array} records 血糖记录列表
   * @returns {Promise<Array>} 保存结果
   */
  async saveGlucoseRecords(records) {
    const results = [];
    
    for (const record of records) {
      try {
        // 调用API保存血糖记录
        const response = await api.health.addGlucoseRecord({
          value: record.value,
          measuredAt: record.measuredAt,
          mealTime: record.mealTime,
          deviceId: record.deviceId,
          deviceName: record.deviceName
        });
        
        results.push(response);
      } catch (error) {
        console.error('保存血糖记录失败:', error);
      }
    }
    
    return results;
  },
  
  /**
   * 保存血压记录
   * @param {Array} records 血压记录列表
   * @returns {Promise<Array>} 保存结果
   */
  async saveBloodPressureRecords(records) {
    const results = [];
    
    for (const record of records) {
      try {
        // 调用API保存血压记录
        const response = await api.health.addBloodPressureRecord({
          systolic: record.systolic,
          diastolic: record.diastolic,
          pulse: record.pulse,
          measuredAt: record.measuredAt,
          deviceId: record.deviceId,
          deviceName: record.deviceName
        });
        
        results.push(response);
      } catch (error) {
        console.error('保存血压记录失败:', error);
      }
    }
    
    return results;
  },
  
  /**
   * 保存体重记录
   * @param {Array} records 体重记录列表
   * @returns {Promise<Array>} 保存结果
   */
  async saveWeightRecords(records) {
    const results = [];
    
    for (const record of records) {
      try {
        // 调用API保存体重记录
        const response = await api.health.addWeightRecord({
          value: record.value,
          measuredAt: record.measuredAt,
          deviceId: record.deviceId,
          deviceName: record.deviceName
        });
        
        results.push(response);
      } catch (error) {
        console.error('保存体重记录失败:', error);
      }
    }
    
    return results;
  }
};

module.exports = DeviceSyncManager; 
 